<?php
/*Class class20{
	public function __construct(){
		echo  'abc';
	}
	
}
new class20();
die();*/

/*
	* 类与对象 基本概念
	* https://www.php.net/manual/zh/language.oop5.basic.php
	* Adair  zouhdai@gmail.com
	* 2021-08-17
*/
/*namespace NS{
	class ClassName{
		//return 123;
	}

	echo ClassName::class."\n<BR \>";
	echo Does\Not\Exist::class."\n<BR \>";
}*/



echo "\n<BR \>"." --- & 引用 --- "."\n<BR \>";

// Assignment of an object
Class Objectss{
   public $foo="bar";
};

$objectVar = new Objectss();
$reference =& $objectVar;
$assignment = $objectVar;
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );


$objectVar->foo = "qux";
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );


$objectVar = null;
print_r('objectVar :'.$objectVar);
print_r('reference :'.$reference);
print_r($assignment);


echo "\n<BR \>\n<BR \>"." --- const,static,static function --- "."\n<BR \>";
class Classy {

	const       STAT = 'S' ; // no dollar sign for constants (they are always static)
	static     $stat = 'Static' ;
	public     $publ = 'Public' ;
	private    $priv = 'Private' ;
	protected  $prot = 'Protected' ;

	function __construct( ){  }

	public function showMe( ){
	    print '<br> self::STAT: '  .  self::STAT ; // refer to a (static) constant like this
	    print '<br> static::STAT: '  .  static::STAT ; // refer to a (static) constant like this
	    print '<br> self::$stat: ' . self::$stat ; // static variable
	    //print '<br>$this->stat: '  . $this->stat ; // legal, but not what you might think: empty result
	    print '<br>static::$stat: '  . static::$stat ;
	    print '<br>$this->publ: '  . $this->publ ; // refer to an object variable like this
	    print '<br>' ;
	}
}
$me = new Classy( ) ;
$me->showMe( ) ;
//echo $me->STAT;
echo '开始内存：'.memory_get_usage(), ''."\n<BR \>"; 
$tmp = str_repeat('hello', 1000);   
echo '运行后内存：'.memory_get_usage(), ''."\n<BR \>"; 
unset($tmp);   
echo '回到正常内存：'.memory_get_usage()."\n<BR \>";


abstract class dbObject
{   
    const TABLE_NAME='parentConst';
   
    public static function GetAll()
    {
        $c = get_called_class();
        return "SELECT * FROM `".$c::TABLE_NAME."`";
    }      
    public static function getChildConst()
    {
        return "SELECT * FROM `".static::TABLE_NAME."`"; // Late Static Bindings
    }   
    public static function getParentConst()
    {
        return "SELECT * FROM `".self::TABLE_NAME."`";
    }
}

class dbPerson extends dbObject
{    
    const TABLE_NAME='childPersonsConst';
}

class dbAdmin extends dbPerson
{
    const TABLE_NAME='childAdminsConst';
}

echo dbPerson::GetAll()."<br>";//output: "SELECT * FROM `childPersonsConst`"
echo dbAdmin::GetAll()."<br>";//output: "SELECT * FROM `childAdminsConst`"

echo dbPerson::getChildConst()."<br>";//output: "SELECT * FROM `childPersonsConst`"
echo dbAdmin::getChildConst()."<br>";//output: "SELECT * FROM `childAdminsConst`"

echo dbPerson::getParentConst()."<br>";//output: "SELECT * FROM `parentConst`"
echo dbAdmin::getParentConst()."<br>";//output: "SELECT * FROM `parentConst`"

class SomeClass {
	const thing = 0;
	const thing2 = 1;
}

$m0 = memory_get_usage();
$p0 = new SomeClass();
$p1 = new SomeClass();
$p2 = new SomeClass();
$m1 = memory_get_usage();
var_dump($p0,$p1,$p2) ;
printf("memory %d<br />", $m1 - $m0)."\n<BR \>\n<BR \>";

class a {

    public static $foo = 'I am foo';
    public $bar = 'I am bar';
   
    public static function getFoo() { echo self::$foo."\n<BR \>";    }
    public static function setFoo() { self::$foo = 'I am a new foo'; }
    public function getBar() { echo $this->bar."\n<BR \>";    }           
}

$ob = new a();
a::getFoo();     // output: I am foo   
$ob->getFoo();    // output: I am foo
//a::getBar();     // fatal error: using $this not in object context
$ob->getBar();    // output: I am bar
                // If you keep $bar non static this will work
                // but if bar was static, then var_dump($this->bar) will output null

// unset($ob);
a::setFoo();    // The same effect as if you called $ob->setFoo(); because $foo is static
$ob = new a();     // This will have no effects on $foo
$ob->getFoo();    // output: I am a new foo


echo "\n<BR \>"." --- __toString 魔术方法 1. 当对象被当做String使用时，__tostring()会被自动调用 --- "."\n<BR \>";
class Point3D
{
    public $x;
    public $y;
    public $z;                  // the x coordinate of this Point.

    /*
     * use the x and y variables inherited from Point.php.
     */
    public function __construct($xCoord=0, $yCoord=0, $zCoord=0)
    {
        $this->x = $xCoord;
    	$this->y = $yCoord;
        $this->z = $zCoord;
    }

    /*
     * the (String) representation of this Point as "Point3D(x, y, z)".
     */
    public function __toString()
    {
        return 'Point3D(x=' . $this->x . ', y=' . $this->y . ', z=' . $this->z . ')';
    }
}



class Line3D
{
    public $start;
    public $end;

    public function __construct($xCoord1=0, $yCoord1=0, $zCoord1=0, $xCoord2=1, $yCoord2=1, $zCoord2=1)
    {	
    	//魔术方法 1. 当对象被当做String使用时，__tostring()会被自动调用
        $this->start = new Point3D($xCoord1, $yCoord1, $zCoord1);
        $this->end = new Point3D($xCoord2, $yCoord2, $zCoord2);
    }

    /*
     * calculate the length of this Line in 3-dimensional space.
     */
    public function getLength()
    {
        return sqrt(
            pow($this->start->x - $this->end->x, 2) +
            pow($this->start->y - $this->end->y, 2) +
            pow($this->start->z - $this->end->z, 2)
        );
    }

    /*
     * The (String) representation of this Line as "Line3D[start, end, length]".
     */
    public function __toString()
    {
        return 'Line3D[start=' . $this->start .
            ', end=' . $this->end .
            ', length=' . $this->getLength() . ']';
    }
}

/*
* create and display objects of type Line3D.
*/
echo '<p>' . (new LINE3D()) . "</p>\n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 0)) . "</p>\n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 100)) . "</p>\n";



echo "\n<BR \>"." --- instanceof作用 --- "."\n<BR \>"; 
//instanceof 作用：（1）判断一个对象是否是某个类的实例，（2）判断一个对象是否实现了某个接口。
class bAr{}
$t = new Bar();
$u = new bar();
//var_dump($t,$u);

echo ($t instanceof $u) ? "true" : "false";// "true"
echo "\n<BR \>"; 
echo ($t instanceof BAR) ? "true" : "false"; // "true"
echo "\n<BR \>"; 
echo is_a($u, 'baR') ? "true" : "false"; // "true"
echo "\n<BR \>"; 
echo get_class($t)."\n<BR \>"; 



echo "\n<BR \>"." --- Anonymous this exactly do --- "."\n<BR \>"; 
class toop {
    public $i = "1234";
    public function setv($a) {
        $this->i = $a;
    }
    public function returnthis() {
        return $this;
    }
}
$ob = new toop();
$ob1 = new toop();
$obthis = $ob->returnthis();
echo $ob->i."\n<BR \>"; 
$ob->setv("\$ob set");
echo $ob->i."\n<BR \>"; 
$obthis->setv("\$obthis set");
echo $ob->i."\n<BR \>"; 
$ob1->setv('$ob1 set');
echo $ob->i."\n<BR \>"; 